package com.ruoyi.app.framework.interceptor;

import java.lang.reflect.Method;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSON;
import com.ruoyi.app.controller.member.mapper.IMemberMapper;
import com.ruoyi.app.controller.shop.mapper.IShopAppletMapper;
import com.ruoyi.app.controller.shop.mapper.IShopMapper;
import com.ruoyi.common.annotation.PassToken;
import com.ruoyi.common.entity.DO.member.MemberDO;
import com.ruoyi.common.entity.DO.shop.ShopDO;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import com.ruoyi.app.common.utils.JwtUtil;

public class AuthenticationInterceptor implements HandlerInterceptor {

    private static final Logger log = LoggerFactory.getLogger("preHandle");

    @Value("${applet.salt}")
    private String salt;

    @Resource
    private IShopAppletMapper shopAppletMapper;

    @Resource
    private IShopMapper shopMapper;

    @Resource
    private IMemberMapper memberMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object object) {
        //如果不是映射到方法直接通过
        if (!(object instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();
        //从请求头中取出token
        String token = request.getHeader("token");
        //检查是否有PassToken注释，有则跳过认证
        if (method.isAnnotationPresent(PassToken.class) && StringUtils.isEmpty(token)) {
            if (method.getAnnotation(PassToken.class).required()) {
                //从请求头中取出appId
                String appId = request.getHeader("appId");
                if (appId != null) {
                    Long shopId = shopAppletMapper.getShopIdByAppId(appId);
                    if (shopId == null || shopId == 0) {
                        throw new BusinessException("通信异常！");
                    }
                    ShopDO shopInfo = shopMapper.selectByPrimaryKey(shopId);
                    if (shopInfo == null || shopInfo.getIsEnable() == 0 || shopInfo.getIsDelete() == 1) {
                        throw new BusinessException("店铺已暂停营业！");
                    }
                    request.setAttribute("shopId", shopId);
                }
//                else {
//                    throw new BusinessException("缺少参数appId！");
//                }
                return true;
            }
        }
        if (token == null) {
            throw new UnauthorizedException("请先授权登录！");
        }
        MemberDO member = JSON.parseObject(JwtUtil.getMember(token), MemberDO.class);
        if (member == null) {
            throw new UnauthorizedException("请重新授权登录！");
        }
        ShopDO shopInfo = shopMapper.selectByPrimaryKey(member.getShopId());
        if (shopInfo == null || shopInfo.getIsEnable() == 0 || shopInfo.getIsDelete() == 1) {
            throw new BusinessException("店铺已暂停营业！");
        }
        // 检验token是否有效
        if(memberMapper.countByOpenidAndId(member.getOpenid(),member.getId())  == 0){
            log.info("脏TOKEN：{},请求时间：{}",token, DateUtils.dateTimeNow());
            throw new UnauthorizedException("请重新授权登录！");
        }
        String signJson = "{\"openid\":\"" + member.getOpenid() + "\",\"id\":" + member.getId() + ",\"shopId\":" + member.getShopId() + "}";
        // 验证token
        if (!JwtUtil.verify(token, signJson, member.getId() + salt)) {
            throw new UnauthorizedException("请重新授权登录！");
        }
        request.setAttribute("memberId", member.getId());
        request.setAttribute("shopId", member.getShopId());
        request.setAttribute("openid", member.getOpenid());
        return true;
    }

}